// main.c - 入口 & 命令循环
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <sys/user.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "bp.h"

static pid_t pid;

void cmd_loop(void) {
    int status;
    uintptr_t addr;
    char cmd[16];
    puts("minidbg> 命令: b addr  c  s  r  q");
    for (;;) {
        printf("mdbg> ");
        fflush(stdout);
        if (scanf("%15s", cmd) != 1) break;
        switch (cmd[0]) {
        case 'b':   // b 0x401000
            if (scanf("%lx", &addr) != 1) { puts("need addr"); break; }
            bp_set(pid, addr);
            break;
        case 'c':   // continue
            if (ptrace(PTRACE_CONT, pid, 0, 0) < 0) perror("PTRACE_CONT");
            waitpid(pid, &status, 0);
            if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP)
                puts("Breakpoint hit");
            break;
        case 's':   // single step
            if (ptrace(PTRACE_SINGLESTEP, pid, 0, 0) < 0) perror("STEP");
            waitpid(pid, &status, 0);
            regs_print();
            break;
        case 'r':   // print regs
            regs_print();
            break;
        case 'q':
            ptrace(PTRACE_DETACH, pid, 0, 0);
            return;
        default:
            puts("Unknown cmd");
        }
    }
}

int main(int argc, char *argv[]) {
    if (argc < 2) { fprintf(stderr, "usage: %s prog [args...]\n", argv[0]); return 1; }
    pid = fork();
    if (pid == 0) {                // child
        ptrace(PTRACE_TRACEME, 0, 0, 0);
        raise(SIGSTOP);            // 同步点
        execvp(argv[1], argv + 1);
        perror("execvp");
        return 127;
    }
    int status;
    waitpid(pid, &status, 0);      // 等待 SIGSTOP
    ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACEEXIT);
    cmd_loop();
    return 0;
}